2.2 数据权限
数据权限是控制用户能访问哪些数据集的CRUD操作,能访问某个数据集的哪些字段(列权限),能访问哪些数据范围(行权限,比如查看自己、查看部门、查看公司层级的数据),以及控制关联查询、子查询的访问。
同时数据权限具备一些高级特性的能力,比如设置为“单独使用的列权限”、“只有返回的列在权限指定的列范围内时才应用”等。
数据权限作用于后端。
1.数据集CRUD访问权限
通过数据权限可以控制对数据集的查询、插入、更新和删除(CRUD)等操作的访问限制。
(1)实现原理
数据库表写入
新建权限后,默认会在门户的数据库表中自动插入1条权限,但未指定角色。角色分配权限后,会自动新插入1条同样的权限,并同时指定角色。
开发时设置写入的是门户的permission_debug表,运行时设置写入的是permission表。
其中code是数据权限的标识,name为用户自定义的名称,type为sql(指数据权限),debug_type为insert,role_id如果未分配给角色则为空。例如:
_condition记录了该权限具体配置的内容,比如这里为CRUD的全部权限,没有限制访问字段和条件。其中S指查询数据,I指插入数据,U指更新数据,D指删除数据。截图如下:
访问约束
当用户访问前端页面的数据内容时,页面会向后端发起dbrest请求,请求会根据数据权限判断用户是否拥有该权限,如果无权限,则请求返回异常,提示无权限。
(2)实现效果
CRUD的操作限制既可以单独设置(比如只能查询数据),也可以多选组合设置(比如可以查询数据和删除数据)。参考如下图所示:
设置访问限制后,在向后端发起请求时返回是否有权限的结果:
同时页面上也会提示异常:
2.数据集字段访问权限(列权限和行权限)
(1)实现原理
数据库表写入
配置完权限后,会在数据库表写入相关内容。其中code是数据权限的标识,name为用户自定义的名称,type为sql(指数据权限),debug_type为insert,role_id如果未分配给角色则为空。例如:
_condition记录了该权限具体配置的内容,比如这里为信息表CRUD的全部权限,同时设置了访问字段和条件。
其中S指查询数据(比如限制只返回createTime,person,title,type等列字段),I指插入数据(比如限制插入type等于财务公告),U指更新数据(比如限制更新type等于财务公告,同时限制where type=财务公告),D指删除数据(比如限制where type=财务公告)。截图如下:
访问约束
当用户访问前端页面的数据内容时,页面会向后端发起dbrest请求,请求会根据数据权限判断用户是否拥有该权限,如果无权限,则请求返回异常,提示无权限。
(2)实现效果
数据集字段的访问权限,可以设置以下几类:
- 某些字段不返回或者不能插入/更新
- 插入数据时可以判断插入的值是否符合要求
- 更新数据时可以判断此次更新是否可以操作,更新的值是否符合要求
- 删除数据时可以判断此次删除是否可以操作
设置访问限制后,在向后端发起请求时返回是否有权限的结果:
同时页面上也会提示异常:
3.数据范围访问权限(行权限)
通过数据范围访问的设置,可以约束用户可以访问哪些数据范围(比如查看自己、查看部门、查看公司层级的数据)。这里通过列权限以及“可用的表达式”的设置来实现。
(1)实现原理
可用的表达式
常用的几个表达式有:
表达式名称 | 表达式 |
---|---|
用户标识 | ${/uaa/userinfo#user_id} |
用户主部门 | ${/context/opm/currentusermainorg?type=dpt#fid} |
用户主机构 | ${/context/opm/currentusermainorg?type=ogn#fid} |
用户岗位 | ${/context/opm/currentusermainorg?type=pos#fid} |
当前日期 | @{CurrentDate()} |
可以通过表达式来设置where条件,比如 销售人员ID 等于 ${/uaa/userinfo#user_id},这样就可以限制登录用户只能查看自己录入的订单信息。
数据库表写入
配置完权限后,会在数据库表写入相关内容。写入的关键内容主要是conditions属性,例如:
访问约束
当用户访问前端页面的数据内容时,页面会向后端发起dbrest请求,此时dbrest会根据权限设置改写sql语句,把where条件加上来限制用户访问的内容。
(2)实现效果
以销售订单为例,普通员工只能查看自己的订单,不能查看其他人的订单;部门领导可以查看部门员工的订单;公司领导可以查看整个公司员工的订单。
录入销售订单数据时,需要录入销售人员ID为上下文组件的获取当前人员成员主键(),销售部门FID为上下文组件的获取当前部门主键全路径()。
权限设置方式如下:
- 普通员工只能查看自己的订单
查询条件设置为:销售人员ID = 用户标识。
- 部门领导可以查看部门员工的订单
查询条件设置为:销售部门FID 包含 用户主部门。
- 公司领导可以查看整个公司员工的订单
查询条件设置为:销售部门FID 包含 用户主机构。
实现效果如下:
- 普通员工查看的数据范围
技术2是普通员工,只能看到技术2自己录入的订单。
- 部门领导查看的数据范围
技术1是技术部的部门领导,可以查看整个技术部人员录入的订单。
- 公司领导查看的数据范围
总经理是公司领导,可以查看整个公司人员录入的订单。
4.关联查询访问权限
在前端页面的数据集,设置关联查询后,join的表也会受到数据权限的约束。
(1)LEFT JOIN
left join权限影响规则:
1、左表会同时受到左表列权限和行权限的影响;
2、右表只受到右表列权限的影响,不受行权限的影响(也就是where条件不起作用)。
以销售订单为例,销售订单的客户ID关联客户表,销售订单 left join 客户(客户为右表),设置客户表的查询数据权限(列只返回客户名称,且客户姓名需等于张三),则查询到的客户信息只有客户名称这个列,且客户只有张三。
客户表(右表)查询权限设置:
关联查询结果(没有返回客户手机号码这列,且客户姓名没有过滤张三这个条件):
(2)RIGHT JOIN
right join权限影响规则:
1、左表只受到左表列权限的影响,不受行权限的影响(也就是where条件不起作用);
2、右表会同时受到右表列权限和行权限的影响。
以销售订单为例,销售订单的客户ID关联客户表,销售订单(左表) right join 客户(右表),设置销售订单(左表)的查询数据权限(只返回订单编码、销售部门和销售人员),设置客户表(右表)的查询数据权限(列只返回客户名称,且客户姓名需等于张三)。
销售订单(左表)查询权限设置:
客户表(右表)查询权限设置:
关联查询结果(销售2登录,但左表并没有过滤销售人员ID这个条件):
(3)INNER JOIN
inner join权限影响规则:
1、左表会同时受到左表列权限和行权限的影响;
2、右表会同时受到右表列权限和行权限的影响。
同样以上边的设置为例,inner join 查询后的结果(左、右表都启用了过滤条件):
5.子查询访问权限
在前端页面的数据集,设置子查询后,子查询的表不会受到数据权限的约束。
以销售订单为例,设置了子查询为客户表,设置如下:
同时客户表设置查询数据权限:
客户表的数据权限只返回客户姓名(并没有返回主键),同时需要过滤客户姓名为张三,但返回的结果显示,子查询并没有经过数据权限的约束,如下图所示:
6.高级特性
(1)单独使用的列权限
数据权限设置为“单独使用的列权限”,设置此属性目的是为了扩大列字段的权限范围。
以查询数据为例,如果存在多个查询权限,列字段默认会做交集返回。如果勾选了其中1个权限的“单独使用的列权限”,此时多个权限的列字段会做并集返回,扩大了返回的列字段范围。
使用场景
在一些使用场景中,有些用户角色需扩展原来权限返回的列字段,但又不想更改原来的权限,此时可以新建1个权限,把这个权限设置为“单独使用的列权限”,再授权给这些用户角色,这样可以添加返回的列字段了。
例子如下:
权限1列字段 | 权限1单独使用的列权限设置 | 权限2列字段 | 权限2单独使用的列权限设置 | 授权效果的列字段(并集) |
---|---|---|---|---|
客户姓名 | 否 | 手机号码、客户状态 | 是 | 客户姓名、手机号码、客户状态 |
实现效果
新建”单独使用的列权限“的查询数据权限前的访问效果:
新建后的访问效果(多了手机号码和客户状态的返回):
注意事项
设置该属性时需要注意以下情况(不能全部权限同时设置该属性),避免使用异常:
权限1列字段 | 权限1单独使用的列权限设置 | 权限2列字段 | 权限2单独使用的列权限设置 | 授权效果的列字段 |
---|---|---|---|---|
客户姓名 | 是 | 全部列字段 | ||
客户姓名 | 是 | 手机号码、客户状态 | 是 | 全部列字段 |
(2)只有返回的列在权限指定的列范围内时才应用
数据权限设置为“只有返回的列在权限指定的列范围内时才应用”,设置此属性目的是为了降低行权限的使用范围,只有在满足返回的列在权限指定的列范围内时,行权限才生效。
使用场景
在一些使用场景中,查看某些列字段的时候,需要设置过滤条件,如果查询的列字段不满足要求,就不需要这些过滤条件。
例如,用户要查看客户的手机号码,只看状态为有效的客户就可以了,状态无效的不需要查看。设置如下:
权限列字段 | 权限行权限 | 是否“只有返回的列在权限指定的列范围内时才应用” |
---|---|---|
客户姓名、手机号码、客户状态 | 客户状态 等于 1 | 是 |
案例说明如下:
案例 | 查询的列字段 | 是否满足权限设置的列字段要求 | 结果 |
---|---|---|---|
案例1 | 客户姓名、客户需求 | 不满足 | 客户状态 等于 1 不生效 |
案例2 | 客户姓名、手机号码、客户状态 | 满足 | 客户状态 等于 1 生效 |
案例3 | 手机号码、客户状态 | 满足 | 客户状态 等于 1 生效 |
实现效果
在前端页面的数据集组件中,可以设置需要返回的列字段:
返回的列字段不满足权限设置要求的访问效果:
返回的列字段满足要求的访问效果(启用了客户状态 等于 1的过滤条件):